package com.xiyuan.smartutils.template.engine;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.constants.CodeConstants;
import com.xiyuan.smartutils.template.engine.exception.ExpressionException;
import com.xiyuan.smartutils.template.engine.expression.Expression;
import com.xiyuan.smartutils.template.engine.expression.operator.*;
import com.xiyuan.smartutils.template.engine.expression.operator.arithmetic.impl.*;
import com.xiyuan.smartutils.template.engine.expression.operator.comparison.*;
import com.xiyuan.smartutils.template.engine.expression.operator.logic._And;
import com.xiyuan.smartutils.template.engine.expression.operator.logic._Not;
import com.xiyuan.smartutils.template.engine.expression.operator.logic._Or;
import com.xiyuan.smartutils.template.engine.expression.operator.logic._Ternary;
import com.xiyuan.smartutils.template.engine.expression.primitive.*;
import com.xiyuan.smartutils.template.engine.expression.symbol.*;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.atomic.AtomicInteger;

@SuppressWarnings({"AlibabaLowerCamelCaseVariableNaming", "AlibabaAvoidStartWithDollarAndUnderLineNaming"})
public class ExpressionParser implements CodeConstants {
    // 标点符号拆分符
    public static final String EXPRESSION_SEPARATOR_CHARS = "<>()[],.+-*/%=|&!?:;";
    private CharSequence src;
    private final AtomicInteger pos = new AtomicInteger(-1);
    // 开始行列
    private int line = 0;
    // 开始行列
    private int column = 0;
    // 文件来源
    private final String path;
    // 临时缓冲区
    private final StringBuilder strb;
    private final ArrayList<Expression> eList = new ArrayList<Expression>();
    
    /**
     * @param line   开始行列
     * @param column 开始行列
     * @param input  表达式内容
     * @param path   内容来源的文件路径
     */
    public ExpressionParser(int line, int column, CharSequence input, String path) {
        this.line = line;
        this.column = column;
        this.path = path;
        this.strb = new StringBuilder(16);
        this.src = "";
        for (int i = 0; i < input.length(); i++) {
            if (!Validates.isWhitespace(input.charAt(i))) {
                this.src = input;
                break;
            }
        }
    }
    
    public int getLine() {
        return line;
    }
    
    public int getColumn() {
        return column;
    }
    
    public boolean hasNext() {
        if (src == null) {return false;}
        
        return pos.get() < (src.length() - 1);
    }
    
    public int nextPos() {
        if (src == null) {return -1;}
        
        if (pos.get() == src.length()) {return src.length();}
        
        return pos.incrementAndGet();
    }
    
    public char next() {
        if (!hasNext()) {return 0;}
        
        char ch = src.charAt(this.nextPos());
        if (ch == '\n') {
            this.line++;
            this.column = 0;
        }
        
        if (ch != '\r' && ch != '\n') {column++;}
        
        return ch;
    }
    
    /**
     * 判断字符是否是表达式分隔符
     *
     * @param c 要求判断的字符
     * @return =true表示是/=false表示否
     */
    public static boolean isExpressionSeparator(char c) {
        return EXPRESSION_SEPARATOR_CHARS.indexOf(c) != -1;
    }
    
    private void add(Expression elem) {
        if (elem == null) {return;}
        
        eList.add(elem);
    }
    
    /**
     * 对表达式中的字符串和字符进行解析 _String和字符串表组成的列表
     *
     * @throws ExpressionException 字符串结束符不匹配
     */
    private void parse_string_char() throws ExpressionException {
        char ch = 0, prvChar = 0, quote = 0;// 字符串符号
        _Unknown un = null;
        int line = this.line, column = this.column;
        while (hasNext()) {
            prvChar = ch;
            ch = next();
            // 进行检查是否为关键字符
            switch (ch) {
                case '\'':// 字符
                {
                    if (prvChar == _BACK_SLASH_) {
                        strb.append(ch);
                        break;// 上一个字符是 “\” 则说明当前不是 字符型
                    }
                    
                    if (strb.length() > 0) {add(un.setValue(strb.toString()));}
                    
                    // 记录开始行列
                    line = this.line;
                    column = this.column;
                    quote = ch;
                    strb.setLength(0);// 重置数据缓冲
                    strb.append(ch);
                    while (hasNext()) {
                        prvChar = ch;
                        ch = next();
                        strb.append(ch);
                        if (ch == quote && prvChar != _BACK_SLASH_) {break;}
                        
                    }
                    
                    String _char = strb.toString();
                    if (ch != quote)// 检查是否为单引号结束
                    {
                        throw new ExpressionException(new _Unknown(path, line, column),
                                                      "字符定义[" + strb + "]格式不正确");
                    }
                    
                    if (!Validates.isLen(_char, 3, 4))// 检查字符长度
                    {
                        throw new ExpressionException(new _Unknown(path, line, column),
                                                      "字符定义[" + strb + "]格式不正确");
                    }
                    
                    char c = strb.charAt(1);
                    // 值长度=4是需要检查 第二个字符是否为转义符
                    if (strb.length() == 4) {
                        if (c != _BACK_SLASH_) {
                            throw new ExpressionException(new _Unknown(path, line, column),
                                                          "字符定义[" + _char + "]格式不正确");
                        }
                        
                        // 检查 第三个字符支持的转义符
                        c = strb.charAt(2);
                        switch (c) {
                            case '\\':
                                c = '\\';
                                break;
                            case '\"':
                                c = '\"';
                                break;
                            case '\'':
                                c = '\'';
                                break;
                            case 'b':
                                c = '\b';
                                break;
                            case 'f':
                                c = '\f';
                                break;
                            case 'r':
                                c = '\r';
                                break;
                            case 'n':
                                c = '\n';
                                break;
                            case 't':
                                c = '\t';
                            case '0':
                                c = '\0';
                                break;
                            default:
                                throw new ExpressionException(new _Unknown(path, line, column),
                                                              "不支持的字符定义[" + _char + "]格式不正确");
                        }
                    }
                    
                    this.add(new _Char(path, line, column, c));
                    strb.setLength(0);// 清空数据
                    break;
                }
                case '\"':// 字符串
                {
                    if (prvChar == _BACK_SLASH_) {
                        strb.append(ch);
                        break;// 上一个字符是 “\” 则说明当前不是 字符型
                    }
                    
                    if (strb.length() > 0) {add(un.setValue(strb.toString()));}
                    
                    // 记录开始行列
                    line = this.line;
                    column = this.column;
                    quote = ch;
                    strb.setLength(0);// 清空数据
                    boolean end = false;
                    while (hasNext()) {
                        ch = next();
                        if (ch == quote && prvChar != _BACK_SLASH_) {
                            end = true;
                            break;// 上一个字符是 “\” 则说明当前不是 字符型
                        }
                        strb.append(ch);
                        prvChar = ch;
                    }
                    if (!end) throw new IllegalArgumentException("未找到字符串定义结束符,当前内容：" + strb);
                    this.add(new _String(path, line, column, strb.toString()));
                    strb.setLength(0);// 清空数据
                    break;
                }
                
                default:
                    strb.append(ch);
                    if (strb.length() == 1) {un = new _Unknown(path, line, this.column);}
                    break;
            }
            
            quote = 0;// 跳出switch 字符串结束
        }
        
        if (strb.length() > 0) {add(un.setValue(strb.toString()));}
        
        // 移除空白的表达式
        for (int i = 0; i < eList.size(); i++) {
            Expression ex = eList.get(i);
            if (ex.getType() == Symbol.SYMBOL_UNKNOWN && Validates.isBlank(ex.toString())) {
                eList.remove(i);
                i--;
            }
        }
        
        // 消除临时变量
        un = null;
        strb.setLength(0);
    }
    
    /***
     * 标点符号拆分内容分
     */
    private void parse_separator(List<Expression> elist) {
        for (ListIterator<Expression> it = elist.listIterator(); it.hasNext(); ) {
            Expression obj = it.next();
            
            if (!(obj instanceof _Unknown)) {
                continue;// 非未知类型补不处理
            }
            
            it.remove();// 剔除当前
            
            _Unknown expression = (_Unknown) obj;
            ArrayList<Expression> expList = new ArrayList<Expression>(1);
            int begin = expression.getLine();
            int column = expression.getColumn();
            String src = expression.getValue();
            if (Validates.isBlank(src)) {
                it.add(obj);
                continue;
            }
            
            _Unknown un = null;
            strb.setLength(0);
            char c = 0;
            for (int i = 0; i < src.length(); i++) {
                c = src.charAt(i);
                if (c == '\n') {
                    begin++;
                    column = 0;
                }
                
                if (c != '\r' && c != '\n' && i > 0) {column++;}
                
                if (Validates.isWhitespace(c) || isExpressionSeparator(c)) {// 被换行了说明表达式结束
                    if (strb.length() > 0) {
                        expList.add(un.setValue(strb.toString()));
                        un = null;
                    }
                    
                    if (isExpressionSeparator(c)) {
                        expList.add(new _Unknown(path, begin, column).setValue(String.valueOf(c)));
                    }
                    
                    strb.setLength(0);
                    continue;
                }
                
                strb.append(c);
                if (strb.length() == 1)// 记录一个未知的 表达式行列号
                {un = new _Unknown(path, begin, column);}
                
            }
            
            if (strb.length() > 0) {expList.add(un.setValue(strb.toString()));}
            
            // 添加解析的到的内容
            for (Expression value : expList) {it.add(value);}
            
            strb.setLength(0);
        }
        
    }
    
    /**
     * _Null/_Boolean/_Gt/_Gte/_Lt/_Lte和标点符号
     *
     * @throws ExpressionException 表达式异常
     */
    private static void parse_symbol(ArrayList<Expression> elist) throws ExpressionException {
        int limit = elist.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = elist.get(i);
            if (!(curr instanceof _Unknown)) {
                continue;// 非未知类型补不处理
            }
            
            _Unknown obj = (_Unknown) curr;
            String val_str = obj.toString();
            if (Validates.isBlank(val_str)) {// 空白的东西不需要
                elist.remove(i);
                limit--;
                i--;
                continue;
            }
            
            String value = StrUtils.trim(val_str);
            Expression target = getExpression(value, obj);
            
            if (target != null) {elist.set(i, target);}
        }
        
        // TODO 检查 运算符 是否重复出现
        
        // 解析双标点符号 .. != == && ||
        limit = elist.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = elist.get(i);
            if (i == 0) {continue;}
            
            Expression prev = elist.get(i - 1);
            switch (curr.getType()) {
                case Symbol.SYMBOL_DOT:// ！号 ‘..’
                {
                    if (prev.getType() == Symbol.SYMBOL_DOT) {
                        ((_Dot) prev).setDouble(true);
                        elist.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
                case Symbol.SYMBOL_EQUAL:// =号 ‘==’ 或者 ‘!=’
                {
                    if (prev.getType() == Symbol.SYMBOL_EQUAL) {// ==
                        ((_Equal) prev).setDouble(true);// 替换（合并）上一个符号为 '=='
                        elist.remove(i);
                        limit--;
                        i--;
                    }
                    else if (prev.getType() == Symbol.SYMBOL_EXCLAMATION) {// !=
                        _InEqual notEqual = new _InEqual(curr.getPath(), prev.getLine(), prev.getColumn());
                        elist.set(i - 1, notEqual);// 替换（合并）上一个符号为 '!='
                        elist.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
                case Symbol.SYMBOL_AMPERSAND:// &号 ‘&&’
                {
                    if (prev.getType() == Symbol.SYMBOL_AMPERSAND) {
                        ((_Ampersand) prev).setDouble(true);// 替换（合并）上一个符号为 '&&'
                        elist.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
                case Symbol.SYMBOL_VERTICAL:// |号 ‘||’
                {
                    if (prev.getType() == Symbol.SYMBOL_VERTICAL) {
                        ((_Vertical) prev).setDouble(true);// 替换（合并）上一个符号为 '||'
                        elist.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
            }
        }
        
        // 判断 gt/gte/lt/lte/new/class 有可能是属性，需要还原为 _Unknown
        limit = elist.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? elist.get(i - 1) : null;
            Expression curr = elist.get(i);
            if (i == 0) {continue;}
            switch (curr.getType()) {
                case Symbol.SYMBOL_GT:
                case Symbol.SYMBOL_GTE:
                case Symbol.SYMBOL_LT:
                case Symbol.SYMBOL_LTE:
                case Primitive.CLASS: {// 还原成变量的条件 ，前面一个是 （[+-*/%?:.,& && | ||
                    
                    boolean flag = i == 0;
                    if (!flag) {
                        switch (prev.getType()) {// 前面出现下列符号则表示，则表示变量
                            case Symbol.SYMBOL_BRACKET_LEFT:// [
                            case Symbol.SYMBOL_PARENTHESIS_LEFT:// (
                            case Symbol.SYMBOL_EQUAL:// 表示赋值
                            case Symbol.SYMBOL_EQUAL_2:// == 条件判断
                            case Symbol.SYMBOL_VERTICAL:// | 条件判断
                            case Symbol.SYMBOL_VERTICAL_2:// || 条件判断
                            case Symbol.SYMBOL_AMPERSAND:// & 条件判断
                            case Symbol.SYMBOL_AMPERSAND_2:// && 条件判断
                            case Symbol.SYMBOL_QUESTION:// ? 三目运算 的取值
                            case Symbol.SYMBOL_COLON:// ： 三目运算 的取值
                            case Symbol.SYMBOL_DOT:// . 点
                            case Symbol.SYMBOL_COMMA:// , 布尔值参数
                            case Symbol.SYMBOL_NOTQUAL:// != 不等于
                            case Symbol.SYMBOL_EXCLAMATION:// ! 取反符号
                            case Symbol.SYMBOL_SEMICOLON:// ; 分号
                            case Symbol.SYMBOL_PLUS:// + 分号
                                // case Symbol.SYMBOL_MINUS:// -
                            case Symbol.SYMBOL_ASTERISK:// *
                            case Symbol.SYMBOL_SLASH:// /
                            case Symbol.SYMBOL_PERCENT:// %
                            case Symbol.SYMBOL_GT:// >
                            case Symbol.SYMBOL_GTE:// >=
                            case Symbol.SYMBOL_LT:// <
                            case Symbol.SYMBOL_LTE:// <=
                                flag = true;
                                break;
                            default:// 其他表示他符号
                                continue;
                        }
                    }
                    
                    if (flag)// 需要还原表示变量
                    {
                        _Unknown unknown = new _Unknown(curr.getPath(), curr.getLine(), curr.getColumn());
                        unknown.setValue(curr.toString());
                        elist.set(i, unknown);
                    }
                    
                    break;
                }
                case Symbol.SYMBOL_NEW: {
                    boolean flag = i == 0;
                    if (!flag && prev.getType() == Symbol.SYMBOL_DOT) {flag = true;}
                    
                    if (flag)// 需要还原表示变量
                    {
                        _Unknown unknown = new _Unknown(curr.getPath(), curr.getLine(), curr.getColumn());
                        unknown.setValue(curr.toString());
                        elist.set(i, unknown);
                    }
                    break;
                }
            }
        }
    }
    
    private static Expression getExpression(String value, _Unknown obj) {
        Expression target = null;
        if (value.length() == 1) {// 一个字符情况下 需要匹配是否为表单符号
            int c = value.length() > 1 ? -1 : value.charAt(0);
            switch (c) {
                // 13个
                case Symbol.SYMBOL_SEMICOLON: // ‘;
                    target = new _Semicolon(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_DOT: // ‘.’
                    target = new _Dot(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_PLUS: // ‘+’
                    target = new _Plus(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_MINUS:// -
                    target = new _Minus(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_ASTERISK: // ‘*’
                    target = new _Asterisk(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_SLASH: // ‘/’
                    target = new _Slash(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_PERCENT: // ‘%’
                    target = new _Percent(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_EXCLAMATION: // ‘!’
                    target = new _Exclamation(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_PARENTHESIS_LEFT: // ‘(’
                    target = new _OpenParenthesis(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_PARENTHESIS_RIGHT:// ‘)’
                    target = new _CloseParenthesis(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_BRACKET_LEFT: // ‘[’
                    target = new _OpenBracket(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_BRACKET_RIGHT: // ‘]’
                    target = new _CloseBracket(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_COMMA: // ‘,’
                    target = new _Comma(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_EQUAL: // ‘=’
                    target = new _Equal(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_QUESTION: // ‘?’
                    target = new _Question(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_COLON: // ‘:’
                    target = new _Colon(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_AMPERSAND: // ‘&’
                    target = new _Ampersand(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
                case Symbol.SYMBOL_VERTICAL: // ‘|’
                    target = new _Vertical(obj.getPath(), obj.getLine(), obj.getColumn());
                    break;
            }
        }
        
        if (target == null) {
            // _Null/_Boolean/_Gt/_Gte/_Lt/_Lte
            boolean isBool = "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
            if (isBool) {target = new _Boolean(obj.getPath(), obj.getLine(), obj.getColumn(), Boolean.parseBoolean(value));}
            else if ("null".equals(value)) {target = new _Null(obj.getPath(), obj.getLine(), obj.getColumn());}
            else if ("gt".equals(value)) {target = new _Gt(obj.getPath(), obj.getLine(), obj.getColumn());}
            else if ("gte".equals(value)) {target = new _Gte(obj.getPath(), obj.getLine(), obj.getColumn());}
            else if ("lt".equals(value)) {target = new _Lt(obj.getPath(), obj.getLine(), obj.getColumn());}
            else if ("lte".equals(value)) {target = new _Lte(obj.getPath(), obj.getLine(), obj.getColumn());}
            else if ("class".equals(value)) {target = new _Class(obj.getPath(), obj.getLine(), obj.getColumn(), value);}
            else if ("new".equals(value)) {target = new _New(obj.getPath(), obj.getLine(), obj.getColumn());}
        }
        return target;
    }
    
    /**
     * 对表达式中的整型进行解析 Integer和字符串表组成的列表
     *
     * @throws ExpressionException 字符串结束符不匹配
     */
    public static void parse_integer(ArrayList<Expression> eList) {
        for (ListIterator<Expression> it = eList.listIterator(); it.hasNext(); ) {
            Expression target = it.next();
            if (!(target instanceof _Unknown)) {
                continue;// 非未知类型补不处理
            }
            
            _Unknown obj = (_Unknown) target;
            String value = StrUtils.trim(obj.toString()).toUpperCase();
            if (Validates.isInteger(value)) {
                it.remove();// 剔除当前
                it.add(new _Integer(obj.getPath(), obj.getLine(), obj.getColumn(), value, false));
            }
            else if (Validates.isInteger(StrUtils.trimRight(value, "L"))) {
                it.remove();// 剔除当前
                it.add(new _Integer(obj.getPath(), obj.getLine(), obj.getColumn(), value, true));
            }
        }
    }
    
    /**
     * 对表达式中的字符\下划线和数值进行解析 _Variable和标点符号
     *
     * @throws ExpressionException 字符串结束符不匹配
     */
    public static void parse_variable(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression o = eList.get(i);
            if (!(o instanceof _Unknown)) {
                continue;// 非未知类型补不处理
            }
            _Unknown obj = (_Unknown) o;
            String val_str = obj.toString();
            if (Validates.isBlank(val_str)) {
                continue;// 空白的东西不许需要
            }
            
            String value = StrUtils.trim(val_str);
            
            if (!Validates.isJavaNameIdentifier(value)) {throw new ExpressionException(obj, "不支持的表达式" + value);}
            
            eList.set(i, new _Variable(obj.getPath(), obj.getLine(), obj.getColumn(), value));
        }
        eList.trimToSize();
    }
    
    /**
     * 解析()括号,成括号表达式
     *
     * @throws ExpressionException 括号未成对出现
     */
    public static void parse_parenthesis(ArrayList<Expression> eList) throws ExpressionException {
        LinkedList<_Parenthesis> ls = new LinkedList<_Parenthesis>();
        _Parenthesis _wrap = null;// 当前括号作用域
        
        // 1. 检查括号作用域
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = eList.get(i);
            switch (curr.getType()) {
                case Symbol.SYMBOL_PARENTHESIS_LEFT: {
                    _Parenthesis _temp_wrap = new _Parenthesis(curr.getPath(), curr.getLine(), curr.getColumn());
                    if (_wrap == null)// 添加在原列表中
                    {eList.set(i, _temp_wrap);}
                    else {
                        _wrap.addExpression(_temp_wrap);// 添加在字列表中
                        eList.remove(i);
                        limit--;
                        i--;
                    }
                    
                    ls.add(_temp_wrap);// 当前括号的作用域
                    _wrap = _temp_wrap;
                    break;
                }
                case Symbol.SYMBOL_PARENTHESIS_RIGHT: {
                    if (ls.isEmpty()) {throw new ExpressionException(curr, "括号()未成对出现, 缺少‘(’");}
                    
                    ls.removeLast();// 移除当前作用域
                    if (_wrap != null) {
                        _wrap.parse();// 解析方阔内容
                    }
                    
                    _wrap = ls.peekLast();// 设置当前作用域
                    eList.remove(i);
                    limit--;
                    i--;
                    break;
                }
                default: {
                    if (_wrap != null) {// 如果在括号中，删除该节点，加入到括号中
                        _wrap.addExpression(curr);
                        eList.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
            }
        }
        
        // 检查是否成对出现
        if (_wrap != null) {throw new ExpressionException(_wrap, "括号()未成对出现");}
        
        // 2. 判断是否前面是前面是 _Variable 或者 new 当前是（）则前面是_Method
        limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            int type = curr.getType();
            if (type != Operator.PARENTHESIS || i == 0) {continue;}
            
            if (prev.getType() == Symbol.SYMBOL_NEW) {
                prev = new _Variable(curr.getPath(), prev.getLine(), prev.getColumn(), prev.toString());
            }
            
            if (prev.getType() != Primitive.VARIABLE) {continue;}
            
            _Method method = new _Method(curr.getPath(),
                                         prev.getLine(),
                                         prev.getColumn(),
                                         ((_Variable) prev).getVariableName());
            eList.set(i - 1, method);// 设置上一个是函数
            method.setParamExpression((_Parenthesis) curr).parse();// 解析参数
            eList.remove(i);
            limit--;
            i--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * 1.组合[]括号，数组括号表达式<br>
     * 2.设置[]数组所属对象<br>
     *
     * @param eList 原型表达式
     * @throws ExpressionException 括号未成对出现
     */
    public static void parse_bracket(ArrayList<Expression> eList) throws ExpressionException {
        LinkedList<_Indexable> ls = new LinkedList<_Indexable>();
        _Indexable _wrap = null;// 当前括号作用域
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = eList.get(i);
            switch (curr.getType()) {
                case Symbol.SYMBOL_BRACKET_LEFT: {
                    ls.add(new _Indexable(curr.getPath(), curr.getLine(), curr.getColumn()));// 当前括号的作用域
                    if (_wrap == null)// 添加在原列表中
                    {eList.set(i, ls.peekLast());}
                    else {
                        _wrap.addExpression(ls.peekLast());// 添加在字列表中
                        eList.remove(i);
                        limit--;
                        i--;
                    }
                    
                    _wrap = ls.peekLast();
                    continue;
                }
                case Symbol.SYMBOL_BRACKET_RIGHT: {
                    if (ls.isEmpty()) {throw new ExpressionException(curr, "括号[]未成对出现, 缺少‘[’");}
                    
                    ls.removeLast();// 移除当前作用域
                    if (_wrap != null) {
                        _wrap.parse();// 解析方阔内容
                    }
                    
                    _wrap = ls.peekLast();// 设置当前作用域
                    eList.remove(i);
                    limit--;
                    i--;
                    continue;
                }
                default: {// 其他表达式
                    if (_wrap != null) {// 如果在括号中，删除该节点，加入到括号中
                        _wrap.addExpression(curr);
                        eList.remove(i);
                        limit--;
                        i--;
                    }
                    break;
                }
            }
        }
        
        // 检查是否成对出现
        if (_wrap != null) {throw new ExpressionException(_wrap, "括号[]未成对出现, 缺少‘]’");}
        
        // 解析数组所属对象
        limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            int type = curr.getType();
            if (type != Operator.INDEXABLE) {continue;}
            
            _wrap = (_Indexable) curr;
            if (i == 0) {
                continue;// 一个的情况
            }
            
            switch (prev.getType()) {// 上一个 标点类型是以下类型
                
                case Primitive.VARIABLE:// 变量
                case Primitive.STRING:// 字符串
                case Operator.PARENTHESIS:// 括号
                case Operator.METHOD:// 方法
                case Operator.INDEXABLE:// 数组
                {
                    // 不允许 [ss,bd,fff,gg][1,2]
                    if (prev.getType() == Operator.INDEXABLE && ((_Indexable) curr).size() != 1) {
                        throw new ExpressionException(curr, "解析[]号时，无法解析" + prev + "对应值表达式" + curr);
                    }
                    
                    _wrap.setLine(prev.getLine()).setColumn(prev.getColumn()).setTarget(prev);
                    eList.set(i - 1, _wrap);
                    eList.remove(i);
                    limit--;
                    i--;
                    break;
                }
                case Symbol.SYMBOL_COMMA:// 逗號
                case Symbol.SYMBOL_QUESTION:// ? 三目必须符号
                case Symbol.SYMBOL_COLON:// : 三目必须符号
                case Symbol.SYMBOL_EQUAL_2:// 判断符号
                    break;
                // break;
                default: {
                    if (prev instanceof Symbol)// 上一是符号原型时
                    {
                        throw new ExpressionException(curr,
                                                      "解析方括号时，前面必须是括号,变量,字符串,整数数组,方法，属性");
                    }
                }
            }
        }
        eList.trimToSize();
    }
    
    /**
     * 解析点号对应的小数、方法，方括号对应的属性
     *
     * @param eList 表达式列表
     * @throws ExpressionException 点号格式不正确
     */
    public static void parse_dot(ArrayList<Expression> eList) throws ExpressionException {
        // *1,前面是数字，后面是数字 2.前面是函数或者变量，后面是属性或者函数*/
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            
            int type = curr.getType();
            if (type != Symbol.SYMBOL_DOT) {continue;}
            
            if (i <= 0) {
                // 第一个就是点号, 那么要求下一个必须为 整形数字
                if (next == null || next.getType() != Primitive.INTEGER) {
                    // 下一个不是整型数字
                    throw new ExpressionException(next, "点号格式不正确。不支持的小数格式");
                }
                
                eList.set(i, new _Decimal(curr.getPath(), next.getLine(), next.getColumn(), "." + next.toString()));
                eList.remove(i + 1);
                limit--;
                continue;
            }
            
            if (i == limit) {
                // 最后一个符号 并且是点号， 那么要求前面一个是数字
                if (prev.getType() != Primitive.INTEGER) {
                    // 下一个不是整型数字
                    throw new ExpressionException(curr, "点号格式不正确。不支持的小数格式");
                }
                eList.set(i - 1, new _Decimal(curr.getPath(), next.getLine(), next.getColumn(), prev.toString() + "."));
                break;
            }
            
            prev.getType();
            if (prev.getType() == Primitive.DECIMAL) {
                // 是小数类型，已经解析过了
                throw new ExpressionException(prev,
                                              "不支持的小数格式：[" + prev.toString() + "." + next.toString() + "]");
            }
            
            if (next.getType() == Primitive.INTEGER) {
                // 后面是数字
                switch (prev.getType()) {
                    case Symbol.SYMBOL_NEW:// new关键字
                    case Primitive.VARIABLE:// _Variable 变量
                    case Primitive.CLASS:// class Java class
                    case Operator.METHOD:// _Method
                    case Operator.INDEXABLE:// 数组表达式
                        throw new ExpressionException(prev, "不支持的小数格式：[" + prev + "." + next + "]");
                }
                
                if (prev.getType() == Primitive.INTEGER) {// 上面一个是数字
                    eList.set(i - 1,
                              new _Decimal(curr.getPath(),
                                           next.getLine(),
                                           next.getColumn(),
                                           prev.toString() + "." + next.toString()));
                    eList.remove(i + 1);// 移除下一个移除当前
                    eList.remove(i);
                    limit -= 2;// 索引个数减两个，
                    i--;// 使得下一轮循环从当前索引开始
                }
                else {// 上面一个不是数字 .66 （.66）等格式
                    eList.set(i, new _Decimal(curr.getPath(), next.getLine(), next.getColumn(), "." + next.toString()));
                    eList.remove(i + 1);
                    limit--;// 索引减两个
                }
                
                continue;
            }
            
            if (prev.getType() == Symbol.SYMBOL_NEW) {// 如果前面是 new 当前是点 那么前面new是变量
                prev = new _Variable(curr.getPath(), prev.getLine(), prev.getColumn(), "new");
                eList.set(i - 1, prev);
                i--;// 索引-1 然后重新检查
                continue;
            }
            
            if (!(next.getType() == Primitive.VARIABLE || next.getType() == Operator.METHOD || next.getType() == Operator.INDEXABLE || next.getType() == Symbol.SYMBOL_NEW)) {
                throw new ExpressionException(prev,
                                              "不支持的小数格式：[" + prev.toString() + "." + next.toString() + "]");
            }
            
            if (next.getType() == Symbol.SYMBOL_NEW) {// 当前是. 下一个是new 说明 new 是属性
                next = new _Variable(curr.getPath(), next.getType(), next.getColumn(), next.toString());
                eList.set(i + 1, next);
            }
            
            if (prev.getType() == Primitive.VARIABLE || prev.getType() == Operator.METHOD || prev.getType() == Operator.INDEXABLE) {// 是变量或者 方法，或者 数组获取的值，则说明 下一个是前一个的属性 或者 方法 或者取值
                Expression ex = null;
                switch (next.getType()) {
                    case Primitive.VARIABLE:// 变量
                        ex = ((_Variable) next).setTarget(prev);
                        break;
                    case Operator.METHOD:
                        ex = ((_Method) next).setTarget(prev);
                        break;
                    case Operator.INDEXABLE:
                        throw new ExpressionException(next, "不正确的‘.’表达式 {" + prev + "." + next + "}");
                }
                eList.set(i - 1, ex);
                eList.remove(i + 1);// 移除当前
                eList.remove(i);// 移除前一个
                limit -= 2;// 索引个数减两个
                i--;// 设置索引指向列表的下一个
            }
            else {throw new ExpressionException(next, "不正确的‘.’表达式 {" + prev + "." + next + "}");}
        }
        
        // 检查中括号的有效性，两种情况。
        // 1、[123,659, ag,a.get()]表示Object数组前面不允许出现 所属对象
        // 2、a[123]表示获取a数组的值，其中[]中不能有多个值
        limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = eList.get(i);
            int type = curr.getType();
            if (type != Operator.INDEXABLE) {continue;}
            
            _Indexable item = (_Indexable) curr;
            if (item.hasTarget() && item.size() != 1) {
                throw new ExpressionException(curr, "数组表达式格式错误，缺少索引表达式");
            }
        }
        eList.trimToSize();
    }
    
    /**
     * 解析双点号，整型数组表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 除号格式不正确
     */
    public static void parse_double_dot(ArrayList<Expression> eList) throws ExpressionException {
        // 数组 解析 双点号
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_DOT_2) {continue;}
            
            if (i == 0 || i == limit) {throw new ExpressionException(curr, "表达式‘..’左或者右表达式为空");}
            
            int pt = prev.getType();
            int nt = next.getType();
            if (pt != Primitive.INTEGER && pt != Primitive.DECIMAL && pt != Operator.METHOD && pt != Operator.INDEXABLE && pt != Operator.PARENTHESIS) {
                throw new ExpressionException(curr, "前后必须数字或变量、方法、属性");
            }
            if (nt != Primitive.INTEGER && nt != Primitive.DECIMAL && nt != Operator.METHOD && nt != Operator.INDEXABLE && nt != Operator.PARENTHESIS) {
                throw new ExpressionException(curr, "前后必须数字或变量、方法、属性");
            }
            
            eList.set(i - 1, new _NumberArray(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next));
            eList.remove(i + 1);
            eList.remove(i);
            limit -= 2;
            i--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * 解析感叹号，取反表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 感叹号格式不正确
     */
    public static void parse_not(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_EXCLAMATION) {continue;}
            
            if (i == limit) {throw new ExpressionException(curr, "取反格式不正确，后面无内容");}
            
            // 判断 取反符号，前面允许 出现的符号
            if (i > 0) {
                switch (prev.getType()) {
                    case Symbol.SYMBOL_EQUAL:// 表示赋值
                    case Symbol.SYMBOL_EQUAL_2:// == 条件判断
                    case Symbol.SYMBOL_VERTICAL:// | 条件判断
                    case Symbol.SYMBOL_VERTICAL_2:// || 条件判断
                    case Symbol.SYMBOL_AMPERSAND:// & 条件判断
                    case Symbol.SYMBOL_AMPERSAND_2:// && 条件判断
                    case Symbol.SYMBOL_QUESTION:// ? 三目运算 的取值
                    case Symbol.SYMBOL_COLON:// ： 三目运算 的取值
                    case Symbol.SYMBOL_COMMA:// , 布尔值参数
                    case Symbol.SYMBOL_NOTQUAL:// != 不等于
                        break;
                    default:
                        throw new ExpressionException(curr,
                                                      "取反格式不正确，前面不允许出现符号【" + prev.toString() + "】");
                }
            }
            
            _Not not = new _Not(curr.getPath(), curr.getLine(), curr.getColumn(), next);
            eList.set(i, not);
            eList.remove(i + 1);
            limit--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * 解析减号中的取负，取负表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 减号号格式不正确
     */
    public static void parse_negative(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_MINUS) {continue;}
            
            if (i == limit) {throw new ExpressionException(curr, "减号/取负号格式不正确，后面无内容");}
            
            if (i > 0) {
                switch (prev.getType()) {// ‘-’前面出现下列符号则表示，则表示负数
                    case Symbol.SYMBOL_BRACKET_LEFT:// [
                    case Symbol.SYMBOL_PARENTHESIS_LEFT:// (
                    case Symbol.SYMBOL_EQUAL:// 表示赋值
                    case Symbol.SYMBOL_EQUAL_2:// == 条件判断
                    case Symbol.SYMBOL_VERTICAL:// | 条件判断
                    case Symbol.SYMBOL_VERTICAL_2:// || 条件判断
                    case Symbol.SYMBOL_AMPERSAND:// & 条件判断
                    case Symbol.SYMBOL_AMPERSAND_2:// && 条件判断
                    case Symbol.SYMBOL_QUESTION:// ? 三目运算 的取值
                    case Symbol.SYMBOL_COLON:// ： 三目运算 的取值
                    case Symbol.SYMBOL_COMMA:// , 布尔值参数
                    case Symbol.SYMBOL_NOTQUAL:// != 不等于
                    case Symbol.SYMBOL_EXCLAMATION:// ! 取反符号
                    case Symbol.SYMBOL_SEMICOLON:// ; 分号
                    case Symbol.SYMBOL_PLUS:// + 分号
                        // case Symbol.SYMBOL_MINUS:// -
                    case Symbol.SYMBOL_ASTERISK:// *
                    case Symbol.SYMBOL_SLASH:// /
                    case Symbol.SYMBOL_PERCENT:// %
                    case Symbol.SYMBOL_GT:// >
                    case Symbol.SYMBOL_GTE:// >=
                    case Symbol.SYMBOL_LT:// <
                    case Symbol.SYMBOL_LTE:// <=
                        break;
                    default:// 其他表示他符号
                        continue;
                }
            }
            
            switch (next.getType()) {// ‘-’ 后面只允许出现以下符号
                case Primitive.INTEGER:// 整形
                case Primitive.DECIMAL:// 小数
                case Primitive.VARIABLE:// 变量
                case Operator.PARENTHESIS:// 小括号运算后的值
                case Operator.METHOD:// 方法的返回值
                case Operator.INDEXABLE:// 数组获取的值
                    break;
                default:// 其他表示他符号
                    continue;
            }
            
            _Negative negative = new _Negative(curr.getPath(), curr.getLine(), curr.getColumn(), next);
            eList.set(i, negative);
            eList.remove(i + 1);
            limit--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * 解析New，创建对象
     *
     * @param eList 表达式列表
     * @throws ExpressionException new格式不正确
     */
    public static void parse_new(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_NEW) {continue;}
            
            if (i == limit) {throw new ExpressionException(curr, "new格式不正确，后面无构造方法");}
            
            if (next.getType() != Operator.METHOD) {throw new ExpressionException(curr, "new格式不正确，后面不是方法");}
            
            _Method _method = (_Method) next;
            Expression _variable = _method.getTarget();
            if (_variable != null) { // 变量所属的对象链 必须都是 变量否则不构成，类名或者方法名
                Expression temp = _variable;
                while (temp != null) {
                    if (temp.getType() != Primitive.VARIABLE) {
                        throw new ExpressionException(curr, "new类名【" + Primitive.VARIABLE + "】格式不正确");
                    }
                    
                    temp = temp.getTarget();
                }
            }
            _method.setNew(true);
            eList.remove(i);
            limit--;
            // i--;// 这里不需要定位了，因为下一个已经明白不是 new 关键字了，所以直接定位到 next next
        }
        
        eList.trimToSize();
    }
    
    /**
     * 解析乘除求模算术表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 格式不正确
     */
    public static void parse_muliplication_division_modulus(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_ASTERISK && type != Symbol.SYMBOL_SLASH && type != Symbol.SYMBOL_PERCENT) {
                continue;
            }
            
            if (i == 0 || i == limit) {throw new ExpressionException(curr, "乘除模表达式格式不正确，前面或后面无内容");}
            
            Expression _te = null;
            switch (type) {
                case Symbol.SYMBOL_ASTERISK:
                    _te = new _Multiplication(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_SLASH:
                    _te = new _Division(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_PERCENT:
                    _te = new _Modulus(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
            }
            
            eList.set(i - 1, _te);// 设置上一个为当前
            eList.remove(i + 1);// 移除下一个
            eList.remove(i);// 移除当前
            limit -= 2;
            i--;// 设置下一轮循环从当前索引开始
        }
        
        eList.trimToSize();
    }
    
    /**
     * 解析加法或字符串连接表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 格式不正确
     */
    public static void parse_add_subtraction(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            if (type != Symbol.SYMBOL_PLUS && type != Symbol.SYMBOL_MINUS) {continue;}
            
            if (i == 0 || i == limit) {throw new ExpressionException(curr, "加减法格式不正确，前面或后面无内容");}
            
            Expression _te = null;
            switch (curr.getType()) {
                case Symbol.SYMBOL_PLUS:
                    _te = new _Add(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_MINUS:
                    _te = new _Subtraction(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
            }
            
            eList.set(i - 1, _te);// 设置上一个为当前
            eList.remove(i + 1);// 移除下一个
            eList.remove(i);// 移除当前
            limit -= 2;
            i--;// 设置下一轮循环从当前索引开始
        }
        
        eList.trimToSize();
    }
    
    /**
     * >、>=、<、<=、== 、!=，|、||、&、&&表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 格式不正确
     */
    public static void parse_gt_gte_lt_lte_eq_eqeq_neq_logic(ArrayList<Expression> eList) throws ExpressionException {
        // 比较表达式
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            switch (type) {
                case Symbol.SYMBOL_GT:
                case Symbol.SYMBOL_GTE:
                case Symbol.SYMBOL_LT:
                case Symbol.SYMBOL_LTE:
                    break;
                default:
                    continue;// 非 >、>=、<、<= 表达式
            }
            
            if (i == 0 || i == limit || prev instanceof Symbol || next instanceof Symbol) {
                throw new ExpressionException(curr, "表达式 >、>=、<、<= 格式不正确，前面或后面无内容");
            }
            
            Expression op = null;
            switch (type) {
                case Symbol.SYMBOL_GT:
                    op = new _GT(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_GTE:
                    op = new _GTE(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_LT:
                    op = new _LT(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_LTE:
                    op = new _LTE(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
            }
            
            eList.set(i - 1, op);
            eList.remove(i + 1);
            eList.remove(i);
            limit -= 2;
            i--;
        }
        
        // == !=
        limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            
            switch (type) {
                case Symbol.SYMBOL_EQUAL_2:// ==
                case Symbol.SYMBOL_NOTQUAL:// !=
                    break;
                default:
                    continue;// 非 == 、!= 表达式
            }
            
            if (i == 0 || i == limit) {
                throw new ExpressionException(curr, "表达式 == 、!= 格式不正确，前面或后面无内容");
            }
            
            Expression op = null;
            switch (type) {
                case Symbol.SYMBOL_EQUAL_2:
                    op = new _EQ(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Operator.NOT_EQUAL:
                    op = new _NE(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
            }
            
            eList.set(i - 1, op);
            eList.remove(i + 1);
            eList.remove(i);
            limit -= 2;
            i--;
        }
        
        // 逻辑表达式
        limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            int type = curr.getType();
            switch (type) {
                case Symbol.SYMBOL_VERTICAL:
                case Symbol.SYMBOL_VERTICAL_2:
                case Symbol.SYMBOL_AMPERSAND:
                case Symbol.SYMBOL_AMPERSAND_2:
                    break;
                default:
                    continue;// 非 | 、||、&、&&表达式
            }
            
            if (i == 0 || i == limit) {
                throw new ExpressionException(curr, "表达式 | 、||、&、&& 格式不正确，前面或后面无内容");
            }
            
            Expression op = null;
            switch (type) {
                case Symbol.SYMBOL_VERTICAL:
                    op = new _Or(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_VERTICAL_2:
                    op = new _Or(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next).setDouble(true);
                    break;
                case Symbol.SYMBOL_AMPERSAND:
                    op = new _And(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
                    break;
                case Symbol.SYMBOL_AMPERSAND_2:
                    op = new _And(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next).setDouble(true);
                    break;
            }
            
            eList.set(i - 1, op);
            eList.remove(i + 1);
            eList.remove(i);
            limit -= 2;
            i--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * 三目表达式
     *
     * @param eList 表达式列表
     * @throws ExpressionException 格式不正确
     */
    public static void parse_ternary(ArrayList<Expression> eList) throws ExpressionException {
        
        for (int i = 0; i < eList.size(); i++) {
            // 2 获取条件
            Expression condition = i > 0 ? eList.get(i - 1) : null;
            Expression question = eList.get(i);
            if (question.getType() != Symbol.SYMBOL_QUESTION) {continue;}
            
            if (condition == null || i > eList.size() - 3) {
                throw new ExpressionException(question,
                                              "三目运算表达式格式不正确,‘?’符前缺少条件表达式或者后面没有足够选项");
            }
            
            if (condition instanceof Symbol) {
                throw new ExpressionException(question, "三目运算表达式格式不正确,‘?’符前不支持的表达式" + condition);
            }
            
            // 2 再次解析后续是否有三目符，因为第一个表达式 或者 第二个表达式 也有可能时三目符
            // 2.1 查找后续 是否有三目符
            boolean flag = false;
            for (int k = i + 1; k < eList.size(); k++) {
                if (eList.get(k).getType() == Symbol.SYMBOL_QUESTION) {
                    flag = true;
                    break;
                }
            }
            
            // 2.1 解析后续三目符
            if (flag) {
                ArrayList<Expression> ls2 = new ArrayList<Expression>(eList.size() - i);
                for (int k = i + 1; k < eList.size(); k++) {ls2.add(eList.get(k));}
                
                parse_ternary(ls2);// 解析后续三目符
                
                // 覆盖原来的表达式列表
                for (int k = i + 1, l = 0; k < eList.size(); k++, l++) {
                    if (l < ls2.size()) {eList.set(k, ls2.get(l));}
                    else {
                        eList.remove(k);
                        k--;// 从当前开始
                    }
                }
            }
            
            // 3 再次判断 是否能够组成三目符
            if (i > eList.size() - 3) {
                throw new ExpressionException(question,
                                              "三目运算表达式格式不正确,‘?’符前缺少条件表达式或者后面没有足够选项");
            }
            
            Expression first = eList.get(i + 1);
            Expression colon = eList.get(i + 2);
            Expression second = eList.get(i + 3);
            if (colon.getType() != Symbol.SYMBOL_COLON) {
                throw new ExpressionException(question, "三目运算表达式格式不正确, 未找到符号 ‘:’");
            }
            
            // if (first instanceof Symbol)
            // throw new ExpressionException(first, "三目运算表达式格式不正确, 不支持的结果表达式" + first);
            // if (second instanceof Symbol)
            // throw new ExpressionException(first, "三目运算表达式格式不正确, 不支持的结果表达式" + first);
            // .i...
            // c?a:b
            // 01234
            eList.set(i - 1,
                      new _Ternary(question.getPath(),
                                   question.getLine(),
                                   question.getColumn(),
                                   condition,
                                   first,
                                   second));// 将前面一个设置成整个三目
            eList.remove(i + 3);// 移除second
            eList.remove(i + 2);// 移除：
            eList.remove(i + 1);// 移除first
            eList.remove(i);// 移除?
            i--;// 从当前开始
        }
        eList.trimToSize();
    }
    
    /**
     * Force variable type conversion 小括号类型强转
     **/
    public static void parse_force_conversion_type(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i < limit; i++) {
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            if (curr.getType() != Operator.PARENTHESIS || i == limit || next instanceof Symbol) {
                continue;// 不是括号 或者 是最后一个
            }
            
            ((_Parenthesis) curr).convert(next);
            eList.remove(i + 1);// 移除second
            limit--;
        }
        
        eList.trimToSize();
    }
    
    /***
     * 解析=号赋值符 Assignment
     *
     * @param eList 表达式列表
     * @throws ExpressionException 格式不正确
     */
    public static void parse_assignment(ArrayList<Expression> eList) throws ExpressionException {
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression prev = i > 0 ? eList.get(i - 1) : null;
            Expression curr = eList.get(i);
            Expression next = i < limit ? eList.get(i + 1) : null;
            if (curr.getType() != Symbol.SYMBOL_EQUAL) {
                continue;// 不是= 或者 是最后一个
            }
            
            // 允许赋值的几种情况
            // a[0] 数组|列表|MAP
            // aaa.prop 、aaa().ppp对象属性
            // aaa 变量
            if (prev == null) {throw new ExpressionException(curr, "=号赋值表达式，左边缺少目标变量");}
            if (next == null) {throw new ExpressionException(curr, "=号赋值表达式，右边边缺少值表达式");}
            
            if (prev.getType() != Primitive.VARIABLE && prev.getType() != Operator.INDEXABLE) {
                throw new ExpressionException(curr, "=号赋值表达式，左边目标表达式不是变量或者不是数组指定的索引");
            }
            
            if (prev.getType() == Operator.INDEXABLE && ((_Indexable) prev).isArr()) {
                throw new ExpressionException(curr, "=号赋值表达式，左边目标不是数组指定的索引");
            }
            
            if (prev.getType() == Operator.INDEXABLE && ((_Indexable) prev).subSize() != 1) {
                throw new ExpressionException(curr, "=号赋值表达式，左边目标不是数组只能指定一个索引");
            }
            
            _Voluation voluation = new _Voluation(curr.getPath(), curr.getLine(), curr.getColumn(), prev, next);
            eList.set(i - 1, voluation);
            eList.remove(i + 1);// 移除next
            eList.remove(i);// 移除curr
            limit -= 2;
            i--;
        }
        
        eList.trimToSize();
    }
    
    /**
     * WebPage运算符表达式基类<br>
     * <br>
     * <p>
     * 以下为Java操作符优先级排序<br>
     * 优先级 操作 结合性]<br>
     * 1 后缀运算符 [] . () (函数呼叫) 从左到右<br>
     * 2 单目运算符 ! ~ ++ -- +(单操作数) –(单操作数) 从右到左<br>
     * 3 创建 new 从左到右<br>
     * 4 乘除取模 * / % 从左到右<br>
     * 5 加减 + - 从左到右<br>
     * 6 移位 << >> >>> 从左到右<br>
     * 7 关系 < <= > >= instanceof 从左到右<br>
     * 8 相等 == != 从左到右<br>
     * 9 按位与 & 从左到右<br>
     * 10 按位异或 ^ 从左到右<br>
     * 11 按位或 | 从左到右<br>
     * 12 逻辑与 && 从左到右<br>
     * 13 逻辑或 || 从左到右<br>
     * 14 条件 ? : 从右到左<br>
     * 15 赋值 = += -= *= /= %= ^= <<= >>= >>>= 从右到左 <br>
     * <p>
     * WebPage操作符只实现如下操作符，共22个(其中1个赋值/20个运算表达式)：<br>
     * 1 后缀运算符 [ ] . ( )(方法调用或表达式括号) 从左到右<br>
     * 2 单目运算符 ! –(数值取负) ..(数值最小最大值) 从右到左<br>
     * 3 创建 new 从左到右<br>
     * 4 乘除取模 * / % 从左到右<br>
     * 5 加减 + - 从左到右<br>
     * 6 关系 lt lte gt gte 从左到右<br>
     * 7 相等 == != 从左到右<br>
     * 8 逻辑与 & && 从左到右<br>
     * 9 逻辑或 | || 从左到右<br>
     * 10 赋值 = 从右到左 <br>
     **/
    public static void parse_operators(ArrayList<Expression> eList) throws ExpressionException {
        if (eList.size() <= 1) {return;}
        
        // 1 解析（）括号作用域 以及函数
        parse_parenthesis(eList);
        if (eList.size() <= 1) {return;}
        
        // 2 解析[]括号信息
        parse_bracket(eList);
        if (eList.size() <= 1) {return;}
        
        // 3 解析 ‘.’对应的小数、方法、[]所属表达式对象
        parse_dot(eList);
        if (eList.size() <= 1) {return;}
        
        // 5 解析 ‘..’ 双点号
        parse_double_dot(eList);
        if (eList.size() <= 1) {return;}
        
        // 6 感叹号(取反运算)
        parse_not(eList);
        if (eList.size() <= 1) {return;}
        
        // 7 取负号
        parse_negative(eList);
        if (eList.size() <= 1) {return;}
        
        // 8 new
        parse_new(eList);
        if (eList.size() <= 1) {return;}
        
        // 9 类型强转 (String) a;
        parse_force_conversion_type(eList);
        if (eList.size() <= 1) {return;}
        
        // 10 乘除模表达式
        parse_muliplication_division_modulus(eList);
        if (eList.size() <= 1) {return;}
        
        // 11 加减表达式
        parse_add_subtraction(eList);
        if (eList.size() <= 1) {return;}
        
        // 12 大于小于/大等于/小等于,以及逻辑表达式
        parse_gt_gte_lt_lte_eq_eqeq_neq_logic(eList);
        if (eList.size() <= 1) {return;}
        
        // 13 三目运算
        parse_ternary(eList);
        if (eList.size() <= 1) {return;}
        
        // 14 = 赋值
        parse_assignment(eList);
        if (eList.isEmpty()) {return;}
        
        // 14 检查语句的正确性，去除中间的逗号
        int limit = eList.size() - 1;
        for (int i = 0; i <= limit; i++) {
            Expression curr = eList.get(i);
            // 19.4 清理多余的分号
            if (curr.getType() == Symbol.SYMBOL_SEMICOLON) {
                eList.remove(i);
                limit--;
                i--;
            }
        }
        
        eList.trimToSize();
    }
    
    /****
     * 解析表达式 返回可执行的表达式列表
     * @return 表达时列表
     * @throws ExpressionException 解析异常
     */
    public ArrayList<Expression> parse() throws ExpressionException {
        // 1 解析原型字符串 &char字符
        this.parse_string_char();
        
        // 2.标点符号拆分内容
        this.parse_separator(this.eList);
        
        // 3 解析标点和 _null, _boolen,gt, gte,lt,lte等
        parse_symbol(eList);
        
        // 4.解析数字整型定义
        parse_integer(this.eList);
        
        // 5.解析变量定义
        parse_variable(this.eList);
        
        // 6 检查标点符号生成操作符
        parse_operators(this.eList);
        
        for (int i = 0; i < this.eList.size(); i++) {
            Expression ex = this.eList.get(i);
            
            // 再次移除分号,和逗号
            if (ex.getType() == Symbol.SYMBOL_SEMICOLON || ex.getType() == Symbol.SYMBOL_COMMA) {
                this.eList.remove(i);
                i--;
                continue;
            }
            
            if (ex instanceof Symbol && ex.getType() != Symbol.SYMBOL_COMMA) {
                throw new ExpressionException(ex, "不允许调用符号表达式{" + ex + "}");
            }
        }
        this.eList.trimToSize();
        
        return this.eList;
    }
}
